<template>
  <div class="file-uploader">
    <!-- 上传区域 -->
    <el-upload
      ref="upload"
      :action="action"
      :auto-upload="autoUpload"
      :file-list="fileList"
      :on-preview="handlePreview"
      :on-remove="handleRemove"
      :on-success="handleSuccess"
      :on-error="handleError"
      :on-progress="handleProgress"
      :before-upload="beforeUpload"
      :headers="headers"
      list-type="picture-card"
    >
      <i v-if="fileList.length < limit" class="el-icon-plus"></i>
      <div v-if="fileList.length >= limit" class="upload-limit-text">
        已达最大上传数量 {{ limit }} 个
      </div>
    </el-upload>

    <!-- 预览模态框 -->
    <el-dialog :visible.sync="previewVisible" title="文件预览" width="50%">
      <div class="preview-container">
        <img :src="previewUrl" alt="预览图" class="preview-image">
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="previewVisible = false">关闭</el-button>
        </span>
      </template>
    </el-dialog>

    <!-- 上传进度提示 -->
    <div v-if="showProgress" class="progress-container">
      <el-progress
        :percentage="progress"
        :status="progress >= 100 ? 'success' : ''"
        :format="progressFormat"
      ></el-progress>
      <div v-if="progress >= 100" class="upload-success-tip">
        <i class="el-icon-success success-icon"></i>
        <span>上传成功</span>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'FileUploader',
  props: {
    // 上传接口地址
    action: {
      type: String,
      default: '/file/minio/upload'
    },
    // 是否自动上传
    autoUpload: {
      type: Boolean,
      default: true
    },
    // 允许上传的文件类型
    accept: {
      type: String,
      default: ''
    },
    // 最大上传文件数量
    limit: {
      type: Number,
      default: 5
    },
    // 已上传的文件列表
    fileList: {
      type: Array,
      default: () => []
    },
    // 上传文件大小限制(MB)
    maxSize: {
      type: Number,
      default: 10
    }
  },
  data() {
    return {
      previewVisible: false,
      previewUrl: '',
      progress: 0,
      showProgress: false
    }
  },
  computed: {
    // 获取请求头，添加token认证
    headers() {
      const token = this.$store.getters.token;
      return {
        'Authorization': 'Bearer ' + token
      };
    }
  },
  methods: {
    // 上传前校验
    beforeUpload(file) {
      // 校验文件大小
      const isLt = file.size / 1024 / 1024 < this.maxSize;
      if (!isLt) {
        this.$message.error(`上传文件大小不能超过 ${this.maxSize}MB!`);
        return false;
      }

      // 校验文件类型
      if (this.accept && file.type && !file.type.match(new RegExp(this.accept))) {
        this.$message.error('请上传正确格式的文件!');
        return false;
      }

      this.showProgress = true;
      this.progress = 0;
      return true;
    },
    // 处理文件预览
    handlePreview(file) {
      // 处理预览URL
      if (file.response && file.response.url) {
        this.previewUrl = file.response.url;
      } else if (file.url) {
        this.previewUrl = file.url;
      } else {
        this.$message.warning('无法预览此文件类型');
        return;
      }
      this.previewVisible = true;
    },
    // 处理文件移除
    handleRemove(file) {
      // 触发文件移除事件
      this.$emit('remove', file);

      // 如果是已上传的文件，需要通知父组件删除
      if (file.response && file.response.fileId) {
        this.$emit('deleteFile', file.response.fileId);
      }
    },
    // 处理上传成功
    handleSuccess(response, file) {
      this.progress = 100;

      // 处理RuoYi-Vue接口返回格式
      if (response.code === 200) {
        const fileData = response.data;

        // 构建文件对象
        const newFile = {
          ...file,
          response: fileData,
          url: fileData.url || file.url
        };

        // 触发上传成功事件，传递文件信息
        this.$emit('success', newFile);

        // 触发文件变更事件，传递更新后的文件列表
        this.$emit('update:fileList', this.getUploadedFiles());

        // 显示成功消息
        this.$message.success(`文件 ${file.name} 上传成功`);
      } else {
        // 处理上传失败
        this.handleError(new Error(response.msg || '上传失败'), file);
      }
    },
    // 处理上传错误
    handleError(error, file) {
      this.progress = 0;
      this.$message.error('文件上传失败，请重试!');

      // 触发上传失败事件
      this.$emit('error', file, error);
    },
    // 处理上传进度
    handleProgress(progress, file) {
      this.progress = progress;
    },
    // 进度格式化
    progressFormat(percentage) {
      if (percentage >= 100) {
        return '上传完成';
      }
      return `${percentage}%`;
    },
    // 获取已上传的文件列表
    getUploadedFiles() {
      return this.fileList.filter(file => file.response);
    },
    // 手动上传文件
    uploadFiles() {
      this.$refs.upload.submit();
    },
    // 清空上传文件
    clearFiles() {
      // 先移除所有文件
      this.fileList.forEach(file => {
        if (file.response && file.response.fileId) {
          this.$emit('deleteFile', file.response.fileId);
        }
      });

      // 重置文件列表
      this.$emit('update:fileList', []);
      this.$refs.upload.clearFiles();
    }
  }
}
</script>

<style scoped>
.file-uploader {
  width: 100%;
}

.upload-limit-text {
  color: #909399;
  font-size: 12px;
  line-height: 180px;
  text-align: center;
}

.progress-container {
  margin-top: 10px;
  width: 100%;
}

.upload-success-tip {
  display: flex;
  align-items: center;
  color: #67c23a;
  margin-top: 5px;
  font-size: 14px;
}

.success-icon {
  margin-right: 5px;
  font-size: 16px;
}

.preview-container {
  display: flex;
  justify-content: center;
  padding: 20px 0;
}

.preview-image {
  max-width: 100%;
  max-height: 400px;
  object-fit: contain;
}
</style>
